#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#define CHEIO 100
void* producer(void*);
void* consumer(void*);

typedef struct {
        pthread_cond_t cond;
        pthread_mutex_t mutex;
        
        int elemento;
} Context;

	Context context[CHEIO];

int main(){

	
	int i;
	for(i = 0; i<=CHEIO; i++){	
		pthread_cond_init(&context[i].cond, NULL);
		pthread_mutex_init(&context[i].mutex, NULL);
	}


        pthread_t prod;
        pthread_t cons;
  	pthread_attr_t attr;

  	pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

	printf("Criando Consumidor\n");
	if(pthread_create(&cons, &attr, consumer, (void*)&context) != 0){
		puts("Could not create consumer thread");
	
		for(i=0; i <=CHEIO; i++){
		pthread_mutex_unlock(&context[i].mutex);
		pthread_cond_signal(&context[i].cond);
	
		pthread_join(prod, NULL);
	
		pthread_mutex_destroy(&context[i].mutex);
		pthread_cond_destroy(&context[i].cond);;
	}
		return(EXIT_FAILURE);
	}
	printf("Criando Produtor\n");
        if(pthread_create(&prod, &attr, producer, (void*)&context) != 0){
                puts("Could not create producer thread");
		for(i = 0; i<=CHEIO; i++){
                pthread_mutex_destroy(&context[i].mutex);
                pthread_cond_destroy(&context[i].cond);
		}
                return(EXIT_FAILURE);
        }

        pthread_join(cons, NULL);
        pthread_join(prod, NULL);

	for(i = 0; i<=CHEIO; i++){
		printf("%d\n",context[i].elemento);
                pthread_mutex_destroy(&context[i].mutex);
                pthread_cond_destroy(&context[i].cond);
		free(&context[i].cond);
        	free(&context[i].mutex);
	}

        return(EXIT_SUCCESS);
}

void* producer(void* conteudo){
	int i, elemento;
	conteudo = (Context*)conteudo;


	printf("produtor\n");
	while(i=0; i<=CHEIO; i++){
		elemento = i*10;

		if((i%5)==0)
		sleep(1);

		pthread_mutex_lock(&context[i].mutex);
		
		printf("Produsindo elemento = %d\n", elemento);
		context[i].elemento = elemento;
		pthread_cond_signal(&context[i].cond);
		pthread_mutex_unlock(&context[i].mutex);
		
	}
  pthread_exit(NULL);
}

void* consumer(void* _context){
	int i, elemento;
	printf("consumidor\n");
	for(i=0; i<=CHEIO; i++){

		pthread_mutex_lock(&context[i].mutex);
		pthread_cond_wait(&context[i].cond, &context[i].mutex);
			
		elemento = context[i].elemento;
		printf("Consumindo o elemento %d = %d\n", i, elemento);

		pthread_mutex_unlock(&context[i].mutex);
	  
	}
pthread_exit(NULL);
}